﻿
package extremefx.conditions {

	/**
	 * @author Marcelo Volmaro
	 */
	public final class ArrayValidator extends Validator {
		private var _array:Array;
		
		public function ArrayValidator(pValue:Array, pArgumentName:String, pAdditionalMessage:String = null) {
			super(pValue, pArgumentName, pAdditionalMessage);
			_array = pValue;
		}
		
		public function isEmpty(pDescription:String = null):ArrayValidator {
			if (_isSequenceNullOrEmpty(_value)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_empty, 
					pDescription, 
					_argumentName
				));
		}
		
		public function isNotEmpty(pDescription:String = null):ArrayValidator {
			if (!_isSequenceNullOrEmpty(_value)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_nEmpty, 
					pDescription, 
					_argumentName
				));
		}
		
		public function contains(pValue:*, pDescription:String = null):ArrayValidator {
			if (_contains(_value, pValue)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_contA, 
					pDescription, 
					_argumentName,
					pValue
				));
		}
		
		public function doesNotContains(pValue:*, pDescription:String = null):ArrayValidator {
			if (!_contains(_value, pValue)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_nContA, 
					pDescription, 
					_argumentName,
					pValue
				));
		}

		public function containsAny(pValues:Array, pDescription:String = null):ArrayValidator {
			if (_containsAny(_value, pValues)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_atLeast, 
					pDescription, 
					_argumentName,
					pValues
				));
		}
		
		public function doesNotContainsAny(pValues:Array, pDescription:String = null):ArrayValidator {
			if (!_containsAny(_value, pValues)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_notAny, 
					pDescription, 
					_argumentName,
					pValues
				));
		}
		
		public function containsAll(pValues:Array, pDescription:String = null):ArrayValidator {
			if (_containsAll(_value, pValues)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_contAll, 
					pDescription, 
					_argumentName,
					pValues
				));
		}
		
		public function doesNotContainsAll(pValues:Array, pDescription:String = null):ArrayValidator {
			if (!_containsAll(_value, pValues)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_nContAll, 
					pDescription, 
					_argumentName,
					pValues
				));
		}
		
		public function hasLength(pNumElements:uint, pDescription:String = null):ArrayValidator {
			if (_array != null && _array.length == pNumElements) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_contX, 
					pDescription, 
					_argumentName,
					pNumElements
				));	
		}
		
		public function doesNotHasLength(pNumElements:uint, pDescription:String = null):ArrayValidator {
			if (_array != null && !(_array.length == pNumElements)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_nContX, 
					pDescription, 
					_argumentName,
					pNumElements
				));	
		}
		
		public function isShorterThan(pNumElements:uint, pDescription:String = null):ArrayValidator {
			if (_array != null && _array.length < pNumElements) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_ncmtX, 
					pDescription, 
					_argumentName,
					pNumElements
				));	
		}
		
		public function isNotShorterThan(pNumElements:uint, pDescription:String = null):ArrayValidator {
			if (_array != null && !(_array.length < pNumElements)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_ncltX, 
					pDescription, 
					_argumentName,
					pNumElements
				));	
		}
		
		public function isShorterOrEqual(pNumElements:uint, pDescription:String = null):ArrayValidator {
			if (_array != null && (_array.length <= pNumElements)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_scXole, 
					pDescription, 
					_argumentName,
					pNumElements
				));	
		}
		
		public function isNotShorterOrEqual(pNumElements:uint, pDescription:String = null):ArrayValidator {
			if (_array != null && !(_array.length <= pNumElements)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_sncXole, 
					pDescription, 
					_argumentName,
					pNumElements
				));	
		}
		
		public function isLongerThan(pNumElements:uint, pDescription:String = null):ArrayValidator {
			if (_array != null && (_array.length > pNumElements)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_scmtXe, 
					pDescription, 
					_argumentName,
					pNumElements
				));	
		}
		
		public function isNotLongerThan(pNumElements:uint, pDescription:String = null):ArrayValidator {
			if (_array != null && !(_array.length > pNumElements)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_sncmtXe, 
					pDescription, 
					_argumentName,
					pNumElements
				));	
		}
		
		public function isLongerOrEqual(pNumElements:uint, pDescription:String = null):ArrayValidator {
			if (_array != null && (_array.length >= pNumElements)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_scXome, 
					pDescription, 
					_argumentName,
					pNumElements
				));	
		}
		
		public function isNotLongerOrEqual(pNumElements:uint, pDescription:String = null):ArrayValidator {
			if (_array != null && !(_array.length >= pNumElements)) return this;
			
			throw _buildException(
				_getFormattedConditionMessage(
					Resources.m_sncXome, 
					pDescription, 
					_argumentName,
					pNumElements
				));	
		}
		
		private function _containsAll(pValues:Array, pEnumerable:Array):Boolean {
			if (_isSequenceNullOrEmpty(pValues)) return true;
			if (_isSequenceNullOrEmpty(pEnumerable)) return false;
			
			for each(var i:* in pValues){
				if (!_contains(i, pEnumerable)) return false;
			}
			
			return true;
		}
		
		private function _containsAny(pValues:Array, pEnumerable:Array):Boolean {
			if (_isSequenceNullOrEmpty(pEnumerable) || _isSequenceNullOrEmpty(pValues)) return false;
			
			
			for each(var i:* in pValues){
				if (_contains(i, pEnumerable)) return true;
			}
			
			return false;
		}
		
		private function _contains(pValue:*, pEnumerable:Array):Boolean {
			if (_isSequenceNullOrEmpty(pEnumerable)) return false;
			
			for each(var i:* in pEnumerable){
				if (i == pValue) return true;
			}
			
			return false;
		}
		
		private function _isSequenceNullOrEmpty(pValue:Array):Boolean {
			if (pValue == null) return true;
			var v:Array = (pValue as Array); 
			return v == null ? true : (v.length != 0);
		}
	}
}
